import {AbilityModel} from "../../controller/model/AbilityModel";
import Configer from "../../frame/apiModel/config/Configer";
import {FinalKey} from "../../constant/FinalConstant";
import {Logger} from "../../frame/apiModel/config/Logger";
import {UnitModel} from "../../frame/apiModel/adapterModel/model3/UnitModel";
import {ItemModel} from "../../frame/apiModel/adapterModel/model3/ItemModel";
import {PlayerModel} from "../../frame/apiModel/adapterModel/model4/PlayerModel";
import {LocModel} from "../../frame/apiModel/base/LocModel";
import {DataRouterUtil} from "../../utils/router/DataRouterUtil";
import {UnitType} from "../../frame/dataSource/DataModel";
import {DataRouter} from "../../frame/dataSource/DataRouter";
import {EffectModel} from "../../frame/apiModel/adapterModel/model2/EffectModel";
import {ModelFactory} from "../../frame/apiModel/adapterModel/model5/ModelFactory";
import {TimeControllerOpt} from "../../controller/model/ControllerOpt";
import {TimeController} from "../../controller/TimeController";
import MathUtil from "../../frame/codeAdapter/MathUtil";
import {SpecialEffectType} from "../../type/Type";
import {ModelType} from "../../frame/apiModel/adapter/adapterInterface/model5/IModelFactory";

export default class HookSkillModel extends AbilityModel {
    abilityId: string = Configer.getFinal(FinalKey.hookSkill) as string;

    actionFun = (activeUnit: UnitModel, activeItem: ItemModel, targetUnit: UnitModel, targetItem: ItemModel, activePlayer: PlayerModel, targetPlayer: PlayerModel, spellId: string, spellLoc: LocModel)  => {
        let success;
        this.hookSkill(activeUnit, activePlayer, spellLoc);
        return success;
    }

    hookSkill (activeUnit: UnitModel, player: PlayerModel, spellLoc: LocModel) {
        const hookSkillId = this.abilityId as string;
        const foreverPeriodic = Configer.getFinal(FinalKey.foreverPeriodic) as number;

        const activeLoc = activeUnit.loc;
        let angle = activeLoc.getAngle(spellLoc);
        const effectArr: { effect: EffectModel, angle: number }[] = [];

        const abilityData = DataRouter.getAbilityDataById(hookSkillId);
        if (abilityData) {
        } else {
            Logger.toastProduct('钩子技能没有经过配置', player)
            return;
        }

        // const xDistance = GetLocationX(spellLoc) - GetLocationX(activeLoc);
        // const yDistance = GetLocationY(spellLoc) - GetLocationY(activeLoc);
        // const distanceEle = (Math.sqrt(xDistance * xDistance + yDistance * yDistance));
        // param
        const range = 100;
        const maxDistance = abilityData.Rng / 25;
        const effectHeadStr = 'abilities\\weapons\\WyvernSpear\\WyvernSpearMissile.mdl';
        const effectLinkStr = 'Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl';
        const toSpeed = 0.01;
        const backSpeed = 0.02;
        const hookLen  = 1;


        const initEffectFun = (effect: EffectModel, initAngle: number) => {
            effect.setSize(2, true);
            effect.angleZ = initAngle;
            effectArr.push({ effect: effect, angle: initAngle });
        }
        const effectHead = TimeController.addSpecialEffectByResourceIdFun(activeUnit, effectHeadStr, foreverPeriodic, activeLoc, undefined, SpecialEffectType.point)

        activeUnit.paused = true;

        let param: { backIndex: number, targetUnit: UnitModel, targetItem: ItemModel } = { backIndex: 1, targetUnit: undefined, targetItem: undefined };

        const checkGetFun = (centerLoc: LocModel, checkRange: number) => {
            if (param.targetUnit) {
                return;
            }
            if (param.targetItem) {
                return;
            }

            // EnumDestructablesInRectAll(rect, () => {
            //     if (destructables) {
            //     } else {
            //         destructables = GetEnumDestructable();
            //     }
            // })

            ModelFactory.getInstance().mapItemsInRange(centerLoc, checkRange, (item) => {
                const isValid = item?.isAlive();
                if (isValid) {
                    param.targetItem = item;
                }
            })

            if (param.targetItem) {
                return;
            }

            ModelFactory.getInstance().mapUnitInRange(centerLoc, range, (unit) => {
                const isAlive = DataRouterUtil.checkUnitUseAttr(unit);
                if (isAlive && (unit !== activeUnit))  {
                    const unitData = DataRouterUtil.getUnitDataByUnit(unit);
                    if (unitData) {
                        param.targetUnit = unit;
                    }
                }
            })
        }

        let indexSum = 0;

        let lastLoc = activeLoc;
        let lastIndex = indexSum;
        let builds: UnitModel[] = [];

        let bPull = false;

        const delCallBack = () => {
            if (effectHead) {
            } else {
                return;
            }
            const backIndex = param.backIndex;
            const currentEffect  = effectArr[backIndex];
            effectArr.splice(backIndex, 1);
            // 获取新的钩子头坐标 或 自己的下一个位置
            const loc = currentEffect.effect.loc;
            const newHeadX = loc.x;
            const newHeadY = loc.y;
            const linkAngle = currentEffect.angle;

            // 清除当前特效坐标
            ModelFactory.getInstance().destroy(currentEffect.effect, ModelType.effect)


            if (bPull) {
            } else {
                param.backIndex = backIndex - 1;
            }


            if (bPull) {
                activeUnit.loc = loc;
            } else {
                // 更新钩子头位置
                effectHead.loc = loc;
                // const headAngle = effectArr[0].angle;
                // EXEffectMatRotateZ(effectHead, -headAngle);
                // EXEffectMatRotateZ(effectHead, linkAngle);
                effectArr[0].angle = linkAngle;
                // 看看新钩子头旁边是否有单位或物品


                // 新钩子头位置的钩子链
                const tempEffect = effectArr[backIndex]

                if (tempEffect) {
                    ModelFactory.getInstance().destroy(tempEffect.effect, ModelType.effect)
                }

                if (param.targetItem || param.targetUnit) {
                    if (param.targetItem) {
                        param.targetItem.loc = loc;
                    } else if (param.targetUnit) {
                        param.targetUnit.loc = loc;
                    }
                } else {
                    const newHeadLoc = new LocModel(newHeadX, newHeadY);
                    checkGetFun(newHeadLoc, range);
                }
            }
            if (effectArr.length === 1) {
                ModelFactory.getInstance().destroy(effectHead, ModelType.effect)
                activeUnit.paused = false;
                // 勾到身边后的判定
            } else {
                const delTimerOpt = new TimeControllerOpt(undefined, delCallBack, 1);
                TimeController.getInstance().startTimer({time: backSpeed, opt: delTimerOpt});
            }
        }


        const callBack = function () {
            if (effectHead) {
            } else {
                return;
            }
            indexSum = indexSum + 1
            lastIndex = lastIndex + 1;
            let locX = lastLoc.x;
            let locY = lastLoc.y;
            const newX = MathUtil.toFixed(locX + (lastIndex + hookLen) * 25 * MathUtil.cos(angle), 6);
            const newY = MathUtil.toFixed(locY + (lastIndex + hookLen) * 25 * MathUtil.sin(angle), 6);
            const newLoc = new LocModel(newX, newY, 100);

            const newEffect = TimeController.addSpecialEffectByResourceIdFun(activeUnit, effectLinkStr, foreverPeriodic, newLoc, undefined, SpecialEffectType.point)
            initEffectFun(newEffect, angle);

            effectHead.loc = newLoc;

            // EnumDestructablesInCircleBJ
            // param.ret = checkGetFun(newLoc, range);

            checkGetFun(newLoc, range);

            let bUse = false;
            if (param.targetUnit) {
                const unitId = param.targetUnit.strId;
                const unitData = DataRouter.getUnitDataByUnitId(unitId);
                const type = unitData && unitData.unit_type;
                if (type === UnitType.hookRebound) {
                    const index = builds.indexOf(param.targetUnit);
                    bUse = true;
                    if (index === -1) {
                        builds.push(param.targetUnit)
                        const unitLoc = param.targetUnit.loc;
                        const linkAngle = newLoc.getAngle(unitLoc);

                        // Util.loggerInDev(`钩子角度${linkAngle}`, LogType.error)
                        // Util.loggerInDev(`当前角度${angle}`, LogType.error)
                        effectHead.angleZ = -angle;
                        angle = 180 -  linkAngle;
                        effectHead.angleZ = angle;
                        effectArr[0].angle = angle;

                        lastLoc = newLoc;
                        lastIndex = 0;
                    }
                }
            }

            if (!bUse && (indexSum >= maxDistance || param.targetUnit || param.targetItem)) {
                if (param.targetUnit) {
                    const unitId = param.targetUnit.strId;
                    const unitData = DataRouter.getUnitDataByUnitId(unitId);
                    if (unitData && unitData.unit_type === UnitType.hookPull) {
                        bPull = true;
                    }
                }
                if (bPull) {
                    param.backIndex = 1;
                } else {
                    param.backIndex = indexSum;
                }
                const delTimerOpt = new TimeControllerOpt(undefined, delCallBack, 1);
                TimeController.getInstance().startTimer({time: backSpeed, opt: delTimerOpt});
            } else {
                const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
                TimeController.getInstance().startTimer({time: toSpeed, opt: timerOpt});
            }
        }
        callBack();
    }
}